package com.fingard.dsp.bank.directbank.jhbank02;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.jhbank02.utils.Decipher;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.util.HashMap;
import java.util.Map;


/**
 * @ClassName JHBANK02Base
 * @Author Zhengzy
 * @Date 2019/12/2 14:36
 * @Version 1.0
 **/
public class JHBANK02Base extends DirectBase implements ITcpClient {
    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            if (p_receiver.readedLength >= 6) {
                String tmpHead = new String(p_receiver.recBytes, 0, 6, getCharset());
                p_receiver.contentLength = Integer.parseInt(tmpHead.trim());
                p_receiver.contentStartIndex = 6;
            }
        }
    }

    /**
     * 获得字符集
     *
     * @return
     */
    protected String getCharset() {
        return "GBK";
    }

    /**
     * 发送报文到银行
     *
     * @param xml
     * @return 银行响应报文
     * @throws Exception
     */
    protected String[] sendToBank(String xml, String cer) throws Exception {
        xml = String.format("%06d%s", xml.getBytes(getCharset()).length, xml);
        WriteBankLogLn("发送给银行的报文明文：" + xml);
        // 加密
        Map<String, String> map = Decipher.encryptData(xml, cer);
        String data = map.get("encryptdata");
        String key = map.get("encryptkey");

        // 组装加密后的报文
        XmlTextWriter encryptXmlWriter = new XmlTextWriter();
        encryptXmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"GBK\" ?>");
        encryptXmlWriter.writeStartElement("root");
        String nodeNo = getBankConfig().getValueAsString("nodeNo");// 机构标识
        encryptXmlWriter.writeElementString("nodeno", nodeNo, true);
        encryptXmlWriter.writeElementString("encryptkey", key);
        encryptXmlWriter.writeElementString("encryptdata", data);
        encryptXmlWriter.writeEndDocument();

        WriteBankUrlLogLn(bankFront.getIpPortOrUrl());
        String[] result = {"", ""};
        xml = encryptXmlWriter.toXmlString();
        xml = String.format("%06d%s", xml.getBytes(getCharset()).length, xml);
        WriteBankLogStep2(xml);
        TcpPortClient client = new TcpPortClient(bankFront.serverIP, Integer.valueOf(bankFront.serverPort), this);
        TcpReceiver receiver = client.sendMessage(xml.getBytes(getCharset()));
        result[0] = receiver.connState;
        if (result[0].length() != 0) {
            result[1] = receiver.connMsg;
            return result;
        }

        result[1] = new String(receiver.recBytes, 0, receiver.contentLength + receiver.contentStartIndex, getCharset());
        WriteBankLogStep3(result[1]);

        if (result[1].length() > 6) {
            result[1] = result[1].substring(6);
        }
        return result;
    }

    /**
     * 写公共报文头
     *
     * @param xmlTextWriter
     * @param header
     */
    protected void writeCommenHeader(XmlTextWriter xmlTextWriter, JHBANK02Header header) {
        xmlTextWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"GBK\" ?>");
        xmlTextWriter.writeStartElement("root");
        xmlTextWriter.writeStartElement("Head");
        xmlTextWriter.writeElementString("userid", header.userid);// 操作号
        xmlTextWriter.writeElementString("brchno", header.brchno, true);// 柜员
        xmlTextWriter.writeElementString("servtp", header.servtp, true);// 渠道
        xmlTextWriter.writeElementString("prcscd", header.prcscd);// 交易号
        xmlTextWriter.writeEndElement();
    }

    /**
     * 验证银行返回签名
     *
     * @param decryptData 解密后的银行数据
     * @return 验签是否成功  成功true，失败false
     * @throws Exception
     */
    protected boolean checkBkSign(String decryptData, String cer) throws Exception {
        StringBuilder tmpSbMsg = new StringBuilder();
        XmlTextReader decryptBkReader = loadBankRespXmlReader(decryptData, tmpSbMsg);
        // 获取<hostReturnCode><hostReturnCode/><hostErrorMessage>< hostErrorMessage/>，与签名进行验证，是否篡改
        int offset = decryptData.indexOf("<hostReturnCode>");
        int endset = decryptData.indexOf("</hostReturnCode>") + "</hostReturnCode>".length();
        String source = decryptData.substring(offset, endset);
        offset = decryptData.indexOf("<hostErrorMessage>");
        endset = decryptData.indexOf("</hostErrorMessage>") + "</hostErrorMessage>".length();
        source = source + decryptData.substring(offset, endset);// 解密内容（签名）

        String hostReturnEncrypt = decryptBkReader.getSimpleText("signature");// 加密内容（签名）

        return Decipher.checkSign(source, hostReturnEncrypt, cer);
    }

    /**
     * 对银行返回报文进行解密
     *
     * @param bankEncryptData 密文
     * @param bankEncryptKey  秘钥
     * @return 解密后的密文
     * @throws Exception
     */
    protected String decrypt(String bankEncryptData, String bankEncryptKey, String pfx) throws Exception {
        Map<String, String> bkMap = new HashMap<String, String>();
        bkMap.put("encryptdata", bankEncryptData);
        bkMap.put("encryptkey", bankEncryptKey);
        return Decipher.decryptData(bkMap, pfx).substring(6);
    }
}
